package com.op.parcel.manage.config.security.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.op.parcel.common.api.R;
import com.op.parcel.common.constant.CommonConstant;
import com.op.parcel.common.constant.SecurityConstant;
import com.op.parcel.manage.config.security.MyUserDetails;
import com.op.parcel.manage.config.security.util.HttpDataUtil;
import com.op.parcel.manage.handler.RedisUser;
import com.op.parcel.manage.modules.sys.entity.Permission;
import com.op.parcel.manage.modules.sys.entity.User;
import com.op.parcel.manage.modules.sys.service.IPermissionService;
import com.op.parcel.manage.modules.sys.service.IUserService;
import com.op.parcel.manage.modules.sys.vo.PermissionVO;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 登录成功处理类
 *
 * @author xuan🐽
 */
@Slf4j
@Component
public class SuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Value("${user.loginTime}")
	private Integer loginTime;

	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private RedisTemplate<String, String> redisTemplate;
	@Autowired
	private IPermissionService permissionService;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
		MyUserDetails principal = (MyUserDetails) authentication.getPrincipal();
		RedisUser redisUser = new RedisUser();
		redisUser.setId(principal.getId());
		Collection<? extends GrantedAuthority> authorities = principal.getAuthorities();
		List<String> permissions = authorities.stream()
			.map(GrantedAuthority::getAuthority)
			.collect(Collectors.toList());

		redisUser.setPermissions(permissions);
		String username = principal.getUsername();
		redisUser.setUsername(username);
		String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + redisUser.getUsername());
		if (StringUtils.isNotBlank(oldToken)) {
			String oldPre = redisTemplate.opsForValue().get(oldToken);
			if (StringUtils.isNotEmpty(oldPre)) {
				redisTemplate.delete(oldPre);
			}
			redisTemplate.delete(oldToken);
		}
		String token = UUID.randomUUID().toString().replaceAll("-", "");
		String userToken = SecurityConstant.TOKEN_PRE + token;
		redisTemplate.opsForValue().set(userToken, objectMapper.writeValueAsString(redisUser), loginTime, TimeUnit.DAYS);
		redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + redisUser.getUsername(), userToken, loginTime, TimeUnit.DAYS);
		Map<String, Object> map = new HashMap<>();
		User user =(User) principal;
		user.setPassword(null);
		map.put("userInfo", user);
		map.put("token", token);
		List<PermissionVO> tree = permissionService.tree(user.getId());
		map.put("menus", tree);
		//TODO xuan 按钮权限（接口）
		List<String> meta = principal.getPermissions().stream()
			.filter(o -> CommonConstant.PERMISSION_INTERFACE.equals(o.getType()))
			.map(Permission::getName).collect(Collectors.toList());
		map.put("permissions", meta);
		HttpDataUtil.respJson(response, R.success(map, "登陆成功"));
	}
}
